React - State
Home

React - State

React - State

Tot nu toe hebben we onze gegevens opgeslagen in een array in een variabele en gaven deze door als props (zie React - Props). Dit is een goed begin, maar wat als we bijvoorbeeld een item uit de array willen verwijderen? Met props hebben we een eenrichtingsgegevensstroom, maar met de state kunnen we privégegevens van een component bijwerken.

Bronnen

  1. State and Lifecycle, deze pagina legt het concept state en lifecycle in een React component uit.

Een nieuwe react app maken

  1. Zorg ervoor dat je openstaande Node.js servers afsluit met Ctrl-C.
  2. Vooraleer de create-react-app op te starten ga je naar de map waarin je het project wil maken. We gaan op Cloud9 een project maken met de naam react-state. En dat project plaatsen we in de root van onze workspace. Zorg er dus voor dat je in de root staat:
    jefinghelbrecht:~/workspace $
    In plaats van JefInghelbrecht zie je natuurlijk de naam van je eigen workspace.
  3. Om een create-react-app te maken, voer je de volgende instructie in je terminal uit (zorg ervoor dat je de laatste versie van Node hebt geïnstalleerd, zie Een React App maken):
    npx create-react-app react-state
    Meer info over npx: Introducing npx: an npm package runner
  4. Op Cloud9 moet je telkens opgeven dat je met de nieuwere versie wilt werken:
    nvm use 8
  5. Als de installatie goed verlopen is, ga dan naar de nieuw aangemaakte map en start het project:
    cd react-state
    npm start
  6. We maken onze eigen standaardtekst en kieperen de voorgeprogrammeerde code overboord. We behouden alleen:
    1. index.js
    2. index.css
  7. We deleten alle overige bestanden in de /src.
  8. In index.css plakken we de Primitive CSS van Tania Rascia. Je kan dat vervangen door je eigen CSS of door Bootstrap of om het even welk ander CSS framework.
  9. Verwijder de verwijzingen naar serviceWorker in index.js. Delete de gemarkeerde lijnen:
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import * as serviceWorker from './serviceWorker';
    
    ReactDOM.render(<App />, document.getElementById('root'));
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: http://bit.ly/CRA-PWA
    serviceWorker.unregister();
    
    

'state' gebruiken om gegevens door te geven

State kan je beschouwen als het opslagen en wijzigen van om het even welk gegeven zonder dat het noodzakelijkerwijs in een database moet worden opgeslagen. Bijvoorbeeld items, die tijdens het shoppen aan een winkelwagentje worden toegevoegd en eventueel weer verwiijderd, vooraleer de aankoop te bevestigen.

  1. We beginnen met het maken van een state-object in het bestand met de naam App.js:
    import React, { Component } from 'react';
    class App extends Component {
        state = {};
    }
    
    export default App;
    
  2. Het state-object bevat al de eigenschappen voor alle gegevens die we in de state willen opslagen. In ons voorbeeld is dat albums:
    import React, { Component } from 'react';
    
    class App extends Component {
      state = {
        albums: []
      };
    }
    
    export default App;
  3. We plaatsen de array met de albums van Jommeke in state.albums:
    import React, { Component } from 'react';
    
    class App extends Component {
      state = {
        albums: [{
            'nummer': '6',
            'titel': 'Het hemelhuis',
            'kaft': 'Softcover',
            'prijs': '€ 5.22'
          },
          {
            'nummer': '7',
            'titel': 'De zwarte Bomma',
            'kaft': 'Softcover',
            'prijs': '€ 5.22'
          },
          {
            'nummer': '8',
            'titel': 'De ooievaar van Begonia',
            'kaft': 'Softcover',
            'prijs': '€ 5.22'
          },
          {
            'nummer': '9',
            'titel': 'De Schildpaddenschat',
            'kaft': 'Softcover',
            'prijs': '€ 5.22'
          },
          {
            'nummer': '10',
            'titel': 'De straalvogel',
            'kaft': 'Hardcover',
            'prijs': '€ 8.22'
          },
          {
            'nummer': '11',
            'titel': 'De Zonnemummie',
            'kaft': 'Softcover',
            'prijs': '€ 5.22'
          }
        ]
      };
    }
    
    export default App;
  4. De gegevens zitten nu in de state. Om een album te kunnen verwijderen uit de tabel, gaan we een removeAlbum methode toevoegen aan de App klasse. Om de state op te vragen halen we this.state.albums op met de ES6 methode, die we in React - Props gebruikt hebben. Om de state te updaten gebruiken we de this.setState() methode. Deze methode is een ingebouwde methode van React om de state te kunnen bewerken. Je moet this.setState() gebruiken om een array te wijzigen. Een nieuwe waarde toekennen aan this.state.property zal niet weken! We zullen de array filteren gebaseerd op de index die we doorgeven. Tenslotte retourneren we de nieuwe gefilterde array. Voeg in App.js de volgende ES6 methode toe:
    import React, { Component } from 'react';
    import Table from './Table';
    
    class App extends Component {
        removeAlbum = index => {
            const { albums } = this.state;
    
            this.setState({
                characters: albums.filter((character, i) => {
                    return i !== index;
                })
            });
        }
       ...
    
    filter muteert niet maar maakt een nieuwe array aan en is dus voorkeursmethode voor het wijzigen van arrays in JavaScript. Deze specifieke methode gaat na of een opgegeven index overeenkomt met één van de indices in de array en het retourneert alle elementen van de array behalve die rij die dezelfde index heeft als de opgegeven index.
  5. We gaan deze functie doorgeven aan de component en een HTML knop weergeven naast elk album die deze functie kan activeren. We geven de removeAlbum functie door als een prop aan de Table component:
    return (
        <div className="container">
            <Table
                albumData={albums}
                removeAlbum={this.removeAlbum}
            />
        </div>
    );
  6. In de return hierboven gebruiken we de albums constante. In React - Props was die in de render() methode gedefinieerd. Nu wordt die in de state van de klasse gedefinieerd. Om die toegankelijk te maken in de render() methode moeten we naar de state verwijzen:
    return (
      <div className="container">
        <Table
            albumData={this.state.albums}
            removeAlbum={this.removeAlbum}
        />
      </div>
    )
  7. We kopiëren de code van de Table component die we gemaakt hebben in React - Props en plaatsen het in een bestand met de naam Table.js in de /src map:
    import React, { Component } from 'react';
    
    const TableBody = props => {
        const rows = props.albumData.map((row, index) => {
            return (
                <tr key={index}>
                    <td>{row.nummer}</td>
                    <td>{row.titel}</td>
                    <td>{row.kaft}</td>
                    <td>{row.prijs}</td>
                </tr>
            );
        });
    
        return <tbody>{rows}</tbody>;
    }
    
    class Table extends Component {
        render() {
            const {albumData} = this.props;
            
            return (
                <table>
                    <TableBody albumData={albumData} />
                </table>
            );
        }
    }
    
    export default Table;
  8. Nu gaan we de removeAlbum methode doorgeven aan het TableBody element van de Table component. We geven de methode door als een prop op dezelfde manier als dat we de albumgegevens hebben doorgegeven:
    class Table extends Component {
        render() {
            const {albumData, removeAlbum} = this.props;
            
            return (
                <table>
                    <TableBody
                        albumData={albumData}
                        removeAlbum = {removeAlbum}
                    />
                </table>
            );
        }
    }
  9. Nu kunnen we eindelijk die index gaan gebruiken die we in de methode removeAlbum gedefinieerd hebben. We geven de key/index aan de TableBody component door als een parameter zodat de filter functie weet welk item er uit de lijst verwijderd moet worden. We maken de HTML knop met een onClick event en geven de index door. In Table.js voegen we de volgende code toe:
    const TableBody = props => {
        const rows = props.albumData.map((row, index) => {
            return (
                <tr key={index}>
                    <td>{row.nummer}</td>
                    <td>{row.titel}</td>
                    <td>{row.kaft}</td>
                    <td>{row.prijs}</td>
                    <td><button onClick={() => props.removeAlbum(index)}>Delete</button></td>
               </tr>
            );
        });
    
        return <tbody>{rows}</tbody>;
    }
    
    Aan het onClick-event kennen we een anonieme functie toe, die de methode removeAlbum() retourneert. Als we dat niet zouden doen dan zou de removeAlbum() functie bij het inladen van de HTML automatisch uitgevoerd worden.
  10. Dit is het resultaat:
    React Table Component With State
    React Table Component With State

JI
2020-04-14 12:21:23